<template>
    <TnxbsvForm ref="form" :model="model" :rules="validationRules" :disabled="disabled">
        <slot></slot>
        <TnxbsvFormGroup v-if="submit !== undefined && submit !== null">
            <div class="flex-v-center">
                <TnxbsvButton :type="theme || 'primary'" :size="size" @click="toSubmit" v-if="submit !== false">
                    {{ _submitText }}
                </TnxbsvButton>
                <TnxbsvButton class="ms-2" :size="size" @click="toCancel" v-if="cancel !== false">
                    {{ cancelText }}
                </TnxbsvButton>
            </div>
        </TnxbsvFormGroup>
    </TnxbsvForm>
</template>

<script>
import TnxbsvForm from '../form/Form.vue';
import TnxbsvFormGroup from '../form/FormGroup.vue';
import TnxbsvButton from '../button/Button.vue';

export default {
    name: 'TnxbsvSubmitForm',
    components: {TnxbsvForm, TnxbsvFormGroup, TnxbsvButton},
    props: {
        model: Object,
        rules: [String, Object], // 加载字段校验规则的URL地址，或规则集对象
        rulesApp: { // 加载字段校验规则的应用名称
            type: String,
            default: () => window.tnx.componentDefaultApp, // 设置为方法以延时加载，确保更改的值生效
        },
        rulesLoaded: Function, // 规则集加载后的附加处理函数，仅在rules为字符串类型的URL地址时有效
        submit: {
            type: [Function, Boolean],
            default: null,
        },
        submitText: String,
        theme: String,
        cancel: {
            type: [String, Function, Boolean],
            default: true
        },
        cancelText: {
            type: String,
            default: '取消'
        },
        errorFocus: {
            type: Boolean,
            default: false,
        },
        size: String,
    },
    emits: ['rules-loaded', 'meta'],
    data() {
        return {
            validationRules: {},
            disabled: false,
            fieldNames: [],
        };
    },
    computed: {
        _submitText() {
            if (this.submitText) {
                return this.submitText;
            }
            return this.cancel === false ? '保存' : '提交';
        }
    },
    watch: {
        rules() {
            this.initRules();
        },
    },
    mounted() {
        this.initRules();
    },
    methods: {
        initRules() {
            if (this.rules) {
                if (typeof this.rules === 'string') {
                    window.tnx.app.rpc.getMeta(this.rules, this.rulesApp).then(meta => {
                        if (this.rulesLoaded) {
                            this.rulesLoaded(meta.$rules);
                        } else {
                            this.$emit('rules-loaded', meta.$rules);
                        }
                        this.validationRules = meta.$rules;
                        delete meta.$rules;
                        this.$emit('meta', meta);
                        this.fieldNames = Object.keys(meta);
                    });
                } else {
                    this.validationRules = {};
                    Object.keys(this.rules).forEach(fieldName => {
                        let fieldRules = this.rules[fieldName] || [];
                        if (!Array.isArray(fieldRules)) {
                            fieldRules = [fieldRules];
                        }
                        if (fieldRules.length) {
                            this.validationRules[fieldName] = fieldRules.filter((rule, index) => {
                                let valid = rule !== undefined && rule !== null;
                                if (!valid) {
                                    console.error(`invalid rules[${index}] for field "${fieldName}": `, rule);
                                }
                                return valid;
                            });
                        }
                    });
                }
            } else {
                this.validationRules = {};
            }
        },
        validate(callback, errorFocus) {
            const promise = this.$refs.form.validate().then(() => {
                return true;
            }).catch(errors => {
                if (this.errorFocus && errorFocus !== false) {
                    this.$nextTick(() => {
                        this.focusError.call(this, errors);
                    });
                }
                return false;
            });
            
            if (typeof callback === 'function') {
                return promise.then(result => {
                    callback(result);
                    return result;
                });
            }
            return promise;
        },
        focusError(errors) {
            let fieldNames = Object.keys(errors);
            let fieldName = fieldNames[0];
            if (fieldName) {
                let fieldElement = this.$refs.form.getFieldElement(fieldName);
                if (fieldElement) {
                    fieldElement.focus();
                    return;
                }
                // 没有找到错误字段输入框，则滚动到错误栏目处
                this.$refs.form.scrollToField(fieldName);
            }
        },
        disable(disabled) {
            this.disabled = disabled !== false;
        },
        toSubmit(callback, disabled) {
            this.validate(success => {
                if (success) {
                    if (typeof callback !== 'function') {
                        callback = this.submit;
                    }
                    if (typeof callback === 'function') {
                        if (disabled !== false) {
                            this.disable();
                        }
                        callback(this);
                    }
                }
            });
        },
        toCancel() {
            if (typeof this.cancel === 'function') {
                this.cancel();
            } else if (typeof this.cancel === 'string') {
                this.$router.back(this.cancel);
            } else if (this.cancel !== false) {
                this.$router.back();
            }
        },
    }
}
</script>

<style>

</style>
